/*
	MP3Player version 0.1
    
    Simple mp3 player.
    
    use:
    - url, pathe to the mp3-file;
    - autoAutplay;
    
    properties you can read:
    - id3, info;
	- length, length in ms;
	- sLength, formatted length "0.00";
	- sPosition, formatted position "0.00";
	- position, position in ms;
	- pMinutes, position minutes;
	- pSeconds, position seconds;
    
    TODO:
    - set position, this is for example for slider-drag;
    - volume;
    - pan;
    - and other cool stuff
    - boring stuff like documentation
    
    Created by Maikel Sibbald
	info@flexcoders.nl
	http://labs.flexcoders.nl
	
	Free to use.... 
*/

package components{
	import com.MusicModelLocator;
	
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.media.ID3Info;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import flash.media.SoundTransform;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;
	
	import mx.collections.ArrayCollection;
	import mx.controls.DataGrid;
	import mx.controls.HSlider;
	import mx.controls.Label;
	import mx.core.UIComponent;
	[Bindable]
	public class MP3Player extends UIComponent{
		
		public var id3:ID3Info;
		[Bindable]
		public var length:Number;
		public var sLength:String					= "00:00";
		public var sPosition:String 				= "00:00";
		public var pMinutes:Number 				= 0;
		public var pSeconds:Number 				= 0;
		public var position:Number 				= 0;
		public var currentTrack:Number 			= -1;
		public var nowPlayingList:ArrayCollection;
		public var dg:DataGrid = null;
		public var lblMsg:Label = null;
		public var errorLblMsg:Label = null;
		
		public var repeat:Boolean = false;

		private var _url:String;
		
		private var _autoPlay:Boolean;
		private var _isPlaying:Boolean = false;
		private var _isPause:Boolean = false;
		private var _volume:Number 				= 1;
		private var	musicModel:MusicModelLocator = MusicModelLocator.getInstance();
		
		private var soundInstance:Sound;
		private var soundChannelInstance:SoundChannel;
		private var trans:SoundTransform = new SoundTransform(1, 0);
		private var urlRequest:URLRequest;
		private var pausePosition:int;
		private var soundBytes:ByteArray;
		
		
		private var lastPosition:Number = 0;
		
		public var blocked:Boolean = false;
		
		public var slider:HSlider;
		
		public var mediaLength:int;
		
		private static var mp3Player:MP3Player;
		public static function getInstance():MP3Player{
			if(mp3Player == null){
				mp3Player = new MP3Player();
			}
			return mp3Player;
		}
		public function MP3Player():void{
			this.explicitHeight = 100;
			this.soundInstance = new Sound();
			this.setupListeners();
		}
		
		public function set url(value:String):void{
			this._url = value;
			this.urlRequest = new URLRequest(this._url);
			this.soundInstance.load(this.urlRequest);
			//trace('set url :' + _url);
		}
		
		public function get url():String{
			//trace('get url :' + _url);
			return _url;
		}
		
		public function setNowPlayingList(value:ArrayCollection):void{
			this.nowPlayingList = value;
			trace(this.nowPlayingList);
		}
			
		public function set autoPlay(value:Boolean):void{
			this._autoPlay = value;
		}
		public function get autoPlay():Boolean{
			return this._autoPlay;
		}
		
		public function set volume(value:Number):void{
			 this._volume = value;
			if(this.soundChannelInstance != null){
				this.trans.volume = this._volume;
				//this.soundChannelInstance.soundTransform.volume = this._volume;
				this.soundChannelInstance.soundTransform = this.trans;
			} 
		}
		
		public function get volume():Number{
			return this._volume;
		}
		
		public function get isPlaying():Boolean{
			return this._isPlaying;
		}
		
		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{
			if(this._autoPlay && !this._isPlaying){
				this.play();
			}
		}
		/******************************************CONTROLS***********************************************/
		private function setupListeners():void{
			this.soundInstance.addEventListener(Event.COMPLETE, completeHandler);
			this.soundInstance.addEventListener(Event.OPEN, openHandler);
			this.soundInstance.addEventListener(Event.ID3, id3Handler);
            this.soundInstance.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
		//	this.soundInstance.addEventListener(ProgressEvent.PROGRESS, progressHandler);
			this.addEventListener( Event.ENTER_FRAME, function():void {
			  if(soundChannelInstance != null){
			  	if(blocked == false){
			  		//slider.value = soundChannelInstance.position;
			  		position = soundChannelInstance.position / 1000;
			  	}
			  	pMinutes = Math.floor(soundChannelInstance.position / 1000 / 60);
			  	pSeconds = Math.floor(soundChannelInstance.position / 1000) % 60;
			  	sPosition = (pMinutes < 10?"0"+pMinutes:pMinutes)+":"+(pSeconds < 10?"0"+pSeconds:pSeconds);
			  	length = soundInstance.length;
				var tempMinutes:Number = Math.floor(length  / 1000 / 60);
				var tempSeconds:Number = Math.floor(length  / 1000) % 60;
				
				sLength = (tempMinutes < 10?"0"+tempMinutes:tempMinutes)+":"+(tempSeconds < 10?"0"+tempSeconds:tempSeconds);
			  }
			}
			);
		}
		public function play():void {
			if(musicModel.nowPlayingList) {
				if(this._isPlaying && !_isPause) {
					stop();
					if(getNextTrack()) {
						play();
					}
				}else {
					_isPause = false;
					if(currentTrack == -1) {
						getTrackAt(0);
					}
					this._isPlaying = true;
					this.soundChannelInstance = this.soundInstance.play(this.pausePosition,1 , this.trans);
					this.trans.volume = this._volume;
					this.soundChannelInstance.soundTransform = this.trans;
					this.soundInstance.addEventListener(Event.ID3, id3Handler);
					this.soundInstance.addEventListener(ProgressEvent.PROGRESS, progressHandler);
					this.soundInstance.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
					this.soundChannelInstance.addEventListener(Event.SOUND_COMPLETE, soundCompleteHandler);
					this.pausePosition = 0;
				}
			}
		}
		
		public function changePosition(from:Number):void {
			if(musicModel.nowPlayingList){
				if(this._isPlaying){
					this.pausePosition = from;
					this.stop();
					this.play();
					//this.blocked = false;
				}
			}
			
		}
		
		public function isRunning():Boolean
		{
			return this._isPlaying;	
		}
		
		public function pause():void{
			if(musicModel.nowPlayingList){
				if(this._isPlaying && !_isPause){
					_isPause = true;
					this.pausePosition = this.soundChannelInstance.position;
					this.stop();
					
				}
			}
		}
		
		private function stop():void{
			if(musicModel.nowPlayingList){
				if(this._isPlaying){
					this._isPlaying = false;
					this.soundChannelInstance.stop();
				}		
			}
		}
	
		public function stopPlayer():void {
			if(musicModel.nowPlayingList){
				if(this._isPlaying){
					this.pausePosition = 0;
					this.stop();
					this.play();
					this.stop();
				}
			}
		}
		
		public function getFirstTrack():Boolean{
			return getTrackAt(0);
		}
		public function getNextTrack():Boolean{
			var i:int;
			//if at end don't do
			if(musicModel.nowPlayingList){
				if(currentTrack < musicModel.nowPlayingList.length - 1){
					i = currentTrack + 1;
					getTrackAt(i);
					return true;
				}else{
					if(repeat) {
						 return getFirstTrack();
					}
				}
			}
			return false;
		}
		public function getPreviousTrack():void{
			var i:int;
			//if at beggining don't do
			if(musicModel.nowPlayingList){
				if(currentTrack > 0){
					i = currentTrack - 1;
					getTrackAt(i);
				}else{
					i = musicModel.nowPlayingList.length - 1;
					getTrackAt(i);					
				}
			}
		}
		public function getLastTrack():void{
			
			var i:int;
			if(musicModel.nowPlayingList){
				i = musicModel.nowPlayingList.length - 1;
				getTrackAt(i);
			}else{
				trace('please choose tracks first');
			}
		}
		public function getTrackAt(i:int):Boolean{
			try{
				if(musicModel.nowPlayingList){
					this.stop();
					this.soundInstance = new Sound();
					var _url:String = musicModel.nowPlayingList.getItemAt(i).filename;
					var _track:String = musicModel.nowPlayingList.getItemAt(i).TrackTitle;
					this.mediaLength = musicModel.nowPlayingList.getItemAt(i).mediaLength;
					
					this.url = _url;
					currentTrack = i;
					var tempDisplayTrack:int = currentTrack + 1;
					
					setMsg( _track );
					trace('currentTrack :' + _track);
					return true;
				}else{
					trace('please choose tracks first');
					this.soundInstance = new Sound();
					this.mediaLength = 0;
					setMsg("none");
					return true;
				}
			}catch (err:Error){
				trace(err);
				//work around for error
				this.stop();
				return this.getNextTrack();
				//setMsg('There was an error, track was skipped, this is still in beta testing, features are being added, and bugs are being fixed, please be patient');
			}
			return false;
		}
		public function setLabel(_Label:Label):void{
			lblMsg = _Label;
			setMsg("none");
		}
		public function setMsg(msg:String):void{
			lblMsg.text = msg;
		}
		public function setErrorLabel(_Label:Label):void{
			errorLblMsg = _Label;
			setErrorMsg("");
		}
		public function setErrorMsg(msg:String):void{
			errorLblMsg.text = msg;
		}
		public function setGrid(_dg:DataGrid):void{
			dg = _dg;
		}
		/******************************************HANDLERS***********************************************/
		private function completeHandler(event:Event):void {
			this.dispatchEvent(event);
        }
        
		private function openHandler(event:Event):void {
			this.dispatchEvent(event);
        }
        
        private function id3Handler(event:Event):void {
			this.id3 = this.soundInstance.id3;
        }

		public function soundCompleteHandler(event:Event):void {
			this.stop();
				this.getNextTrack();
		}
		
        private function ioErrorHandler(event:IOErrorEvent):void {
           this.setErrorMsg("This file failed please try again!");
           trace('in error');
        }

        private function progressHandler(event:ProgressEvent):void {
//        	if(this.soundInstance != null){
//	        	this.length = this.soundInstance.length;
//				var tempMinutes:Number = Math.floor(this.length  / 1000 / 60);
//				var tempSeconds:Number = Math.floor(this.length  / 1000) % 60;
//				
//				this.sLength = tempMinutes+":"+(tempSeconds < 10?"0"+tempSeconds:tempSeconds);
//         	}
//         	this.dispatchEvent(event);
			setErrorMsg("");
        }

	}
}